package com.java.jvm.loader;

import java.io.*;

/**
 * ClassLoader没有抽象方法为什么还要将此类定义为抽象类？外界不允许直接构建此类对象
 */
public class BreakDoubleParentAppClassLoader extends ClassLoader{

    private String baseDir;
    public BreakDoubleParentAppClassLoader(String baseDir){
        this.baseDir=baseDir;
    }

    /**
     * 重写loadClass方法(此方法在父类中是使用双亲委派方式加载类的)
     * @param className
     * @return
     * @throws ClassNotFoundException
     */
    @Override
    public Class<?> loadClass(String className) throws ClassNotFoundException {
        try {
            //自己先去加载自己写写的类
            return findClass(className);
        }catch (ClassNotFoundException e){
            //有些基础类库还是需要使用java自带双亲委派机制去加载。
            return super.loadClass(className);
        }
    }
    @Override
    protected Class<?> findClass(String className) throws ClassNotFoundException {
        //1.获取className实际的物理位置 (com/java/Hello)
        String classFilePath=baseDir+className.replace(".", File.separator)+".class";
        //2.判定此位置的className文件是否存在
        File file=new File(classFilePath);
        if(!file.exists())
            throw new ClassNotFoundException();
        //3.读取class文件
        InputStream in=null;
        byte[] data=null;
        try {
            in=new FileInputStream(file);
            data=new byte[in.available()];
            in.read(data);
            //4.构建字节码对象
            return defineClass(className, data, 0, data.length);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }finally{
            if(in!=null) { try { in.close(); } catch (IOException e) { e.printStackTrace(); } }
        }
    }
}
